package com.example.demo.completable;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * ClassName: CompletableFutureDemo
 * author: bob.ly
 * Version: 1.0.0
 * DateTime: 2021/08/01-14:03:00
 * Description:
 */
public class CompletableFutureDemo {
    private static ExecutorService executorService = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        /**
         * 1: runAsync()和supplyAsync()的区别
         *
         * runAsync():没有返回值, 放一个任务跑就行了
         * supplyAsync(): 有返回值, 放一个任务跑, 最后要什么结果可以返回, 如果调用了get(),会阻塞线程,先拿到返回值
         */
//        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
//            System.out.println("111插入一条数据");
//        }, executorService);
//
//        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("222插入一条数据");
//            return "主键id";
//        }, executorService);
//
//        String s = future2.get();
//        System.out.println(s);
//        System.out.println("我是主线程....");


        /**
         * 2:whenCompleteAsync
         * 里面有两个参数, 1个返回值,1个异常, 但是没有返回值
         * 一般whenCompleteAsync是配合exceptionally一起使用的, 这样就可以由返回值
         */
//        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("222插入一条数据");
//            int i = 10 / 0;
//            return "主键id";
//        }, executorService).whenCompleteAsync((t1, t2) -> {
//            if (t1 != null) {
//                System.out.println("我拿到了数据");
//                System.out.println(t1);
//            }
//            if (t2 != null) {
//                System.out.println("我异常了");
//            }
//        }, executorService).exceptionally(t -> {
//            return "我异常了....";
//        });
//        System.out.println(future2.get());
//        System.out.println("我是主线程....");


        /**
         * 3.用handle()可以代表2中的whenCompleteAsync和exceptionally方法, 相当于一个顶两
         */
//        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
//            System.out.println("222插入一条数据");
//            int i = 10 / 0;
//            return "主键id";
//        }, executorService).handle((t1, t2) -> {
//            if (t1 != null) {
//                System.out.println("我拿到了数据");
//                return "t1";
//            }
//            if (t2 != null) {
//                System.out.println("我异常了");
//                return "t2";
//            }
//            return "我test一下";
//        });
//        System.out.println(future2.get());
//        System.out.println("我是主线程....");

        /**
         * 4:
         * thenApplyAsync(): 当第一个future运行完之后, 第二个future可以拿到第一个的返回值,可以返回新返回值
         * thenAcceptAsync():当第一个future运行完之后, 第二个future可以拿到第一个的返回值, 没有新返回值
         * thenRunAsync(): 当第一个future运行完之后, 第二个future继续做自己的, 没有返回值
         *
         *
         * runAfterBothAsync(): 在a和b都允许完之后, 第三个任务可以坐自己的,自己没有返回值
         * thenAcceptBothAsync(): 在a和b都运行完之后, 第三个任务可以拿到a和b的返回值, 自己没有返回值
         * thenCombineAsync():在a和b都运行完之后, 第三个任务可以拿到a和b的返回值, 自己有返回值
         */
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("我是插入操作");
            return "插入数据";
        }, executorService);
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("数据被查询了...");
            return "数据被查询了...";
        }, executorService);

        CompletableFuture<String> completableFuture = future1.thenCombineAsync(future2, (t1, t2) -> {
            System.out.println(t1);
            System.out.println(t2);
            return "我哈哈哈";
        }, executorService);
        System.out.println(completableFuture.get());
//        future1.thenAcceptBothAsync(future2, (t1, t2) -> {
//            System.out.println(t1);
//            System.out.println(t2);
//        }, executorService);

//        future1.runAfterBothAsync(future2, () -> {
//            System.out.println("我好尴尬,我看到了插入和查询");
//        }, executorService);
//        completableFuture.thenRunAsync(() -> {
//            System.out.println("滚吧");
//        }, executorService);

//        completableFuture.thenAcceptAsync((t1) -> {
//            try {
//                Thread.sleep(1000L);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println("我拿到了你的参数:" + t1);
//        }, executorService);
//        CompletableFuture<String> completableFuture1 = completableFuture.thenApplyAsync((c1) -> {
//            System.out.println(c1);
//            return "你插入了数据";
//        }, executorService);
        System.out.println("我是主线程....");

    }
}
